package com.tao.lab.bitmaprecycle;

import android.annotation.TargetApi;
import android.graphics.Bitmap;

import com.tao.lab.utils.Util;

import java.util.TreeMap;

/**
 * @ProjectName: lab
 * @Package: com.tao.lab.bitmaprecycle
 * @ClassName: SizeStrategy
 * @Description: java类作用描述
 * @Author: wangxf
 * @CreateDate: 2022/5/26 9:27
 * @UpdateUser: 更新者
 * @UpdateDate: 2022/5/26 9:27
 * @UpdateRemark: 更新说明
 * @Version: 1.0
 */
@TargetApi(19)
class SizeStrategy implements LruPoolStrategy {
    private static final int MAX_SIZE_MULTIPLE = 8;
    private final SizeStrategy.KeyPool keyPool = new SizeStrategy.KeyPool();
    private final GroupedLinkedMap<SizeStrategy.Key, Bitmap> groupedMap = new GroupedLinkedMap();
    private final TreeMap<Integer, Integer> sortedSizes = new PrettyPrintTreeMap();

    SizeStrategy() {
    }

    public void put(Bitmap bitmap) {
        int size = Util.getBitmapByteSize(bitmap);
        SizeStrategy.Key key = this.keyPool.get(size);
        this.groupedMap.put(key, bitmap);
        Integer current = (Integer)this.sortedSizes.get(key.size);
        this.sortedSizes.put(key.size, current == null ? 1 : current + 1);
    }

    public Bitmap get(int width, int height, Bitmap.Config config) {
        int size = Util.getBitmapByteSize(width, height, config);
        SizeStrategy.Key key = this.keyPool.get(size);
        Integer possibleSize = (Integer)this.sortedSizes.ceilingKey(size);
        if (possibleSize != null && possibleSize != size && possibleSize <= size * 8) {
            this.keyPool.offer(key);
            key = this.keyPool.get(possibleSize);
        }

        Bitmap result = (Bitmap)this.groupedMap.get(key);
        if (result != null) {
            result.reconfigure(width, height, config);
            this.decrementBitmapOfSize(possibleSize);
        }

        return result;
    }

    public Bitmap removeLast() {
        Bitmap removed = (Bitmap)this.groupedMap.removeLast();
        if (removed != null) {
            int removedSize = Util.getBitmapByteSize(removed);
            this.decrementBitmapOfSize(removedSize);
        }

        return removed;
    }

    private void decrementBitmapOfSize(Integer size) {
        Integer current = (Integer)this.sortedSizes.get(size);
        if (current == 1) {
            this.sortedSizes.remove(size);
        } else {
            this.sortedSizes.put(size, current - 1);
        }

    }

    public String logBitmap(Bitmap bitmap) {
        return getBitmapString(bitmap);
    }

    public String logBitmap(int width, int height, Bitmap.Config config) {
        int size = Util.getBitmapByteSize(width, height, config);
        return getBitmapString(size);
    }

    public int getSize(Bitmap bitmap) {
        return Util.getBitmapByteSize(bitmap);
    }

    public String toString() {
        return "SizeStrategy:\n  " + this.groupedMap + "\n" + "  SortedSizes" + this.sortedSizes;
    }

    private static String getBitmapString(Bitmap bitmap) {
        int size = Util.getBitmapByteSize(bitmap);
        return getBitmapString(size);
    }

    private static String getBitmapString(int size) {
        return "[" + size + "]";
    }

    static final class Key implements Poolable {
        private final SizeStrategy.KeyPool pool;
        private int size;

        Key(SizeStrategy.KeyPool pool) {
            this.pool = pool;
        }

        public void init(int size) {
            this.size = size;
        }

        public boolean equals(Object o) {
            if (o instanceof SizeStrategy.Key) {
                SizeStrategy.Key other = (SizeStrategy.Key)o;
                return this.size == other.size;
            } else {
                return false;
            }
        }

        public int hashCode() {
            return this.size;
        }

        public String toString() {
            return SizeStrategy.getBitmapString(this.size);
        }

        public void offer() {
            this.pool.offer(this);
        }
    }

    static class KeyPool extends BaseKeyPool<SizeStrategy.Key> {
        KeyPool() {
        }

        public SizeStrategy.Key get(int size) {
            SizeStrategy.Key result = (SizeStrategy.Key)this.get();
            result.init(size);
            return result;
        }

        protected SizeStrategy.Key create() {
            return new SizeStrategy.Key(this);
        }
    }
}

